package api

import (
	args "com.yy.api/common/client/agent"
	reply "com.yy.api/common/client/agent"
	"com.yy.api/common/logger"
	"com.yy.api/common/pojo/dto"
	containerParam "com.yy.api/common/pojo/param/container"
	imageParam "com.yy.api/common/pojo/param/image"
	"net/rpc"
)

type AgentApi interface {
	PullImage(param imageParam.PullImageParam) error
	CreateContainer(param containerParam.CreateContainerParam, res *dto.CreateContainerDto) error
	StartContainer(containerId string) error
	InspectContainer(containerIdOrName string, res *dto.InspectContainerDataDto) error
	ListContainers(param containerParam.ListContainerParam, res *dto.ListContainersDto) error
	ReleaseContainer(param containerParam.ReleaseContainerParam, res *dto.ReleaseContainerDto) error
	HasContainer(param containerParam.HasContainerParam, res *dto.HasContainerDto) error
}

type AgentClient struct {
	AgentApi
	AgentAddr string
	client    *rpc.Client
}

func NewAgentClient(agentAddr string) (*AgentClient, error) {
	result := AgentClient{
		AgentAddr: agentAddr,
	}
	if err := result.register(); err != nil {
		logger.Default.Errorf("%s", err)
		return &result, err
	}
	return &result, nil
}

func (ac *AgentClient) register() error {
	conn, err := rpc.DialHTTP("tcp", ac.AgentAddr)
	if err != nil {
		return err
	}
	ac.client = conn
	return nil
}
func (ac *AgentClient) PullImage(param imageParam.PullImageParam) error {
	tArgs := &args.PullImageArgs{
		PullImageParam: param,
	}
	var tReply reply.PullImageReply
	ca := ac.client.Go("Agent.PullImage", tArgs, &tReply, nil)
	<-ca.Done
	if ca.Error != nil {
		return ca.Error
	}
	return nil
}

func (ac *AgentClient) CreateContainer(param containerParam.CreateContainerParam, res *dto.CreateContainerDto) error {

	tArgs := &args.CreateContainerArgs{
		CreateContainerParam: param,
	}
	var tReply reply.CreateContainerReply
	ca := ac.client.Go("Agent.CreateContainer", tArgs, &tReply, nil)
	<-ca.Done
	if ca.Error != nil {
		return ca.Error
	}
	*res = tReply.CreateContainerDto
	return nil
}

func (ac *AgentClient) StartContainer(containerId string) error {

	tArgs := &args.StartContainerArgs{
		StartContainerParam: containerParam.AssembleStartContainerParam(containerId),
	}
	var tReply reply.StartContainerReply
	ca := ac.client.Go("Agent.StartContainer", tArgs, &tReply, nil)
	<-ca.Done
	if ca.Error != nil {
		return ca.Error
	}
	return nil
}

func (ac *AgentClient) InspectContainer(containerIdOrName string, res *dto.InspectContainerDataDto) error {

	tArgs := &args.InspectContainerArgs{
		InspectContainerParam: containerParam.AssembleInspectContainerParam(containerIdOrName),
	}
	var tReply reply.InspectContainerReply
	ca := ac.client.Go("Agent.InspectContainer", tArgs, &tReply, nil)
	<-ca.Done
	if ca.Error != nil {
		return ca.Error
	}
	*res = tReply.InspectContainerDataDto
	return nil
}

func (ac *AgentClient) ListContainers(param containerParam.ListContainerParam, res *dto.ListContainersDto) error {
	tArgs := &args.ListContainersArgs{
		ListContainerParam: param,
	}
	var tReply reply.ListContainersReply
	ca := ac.client.Go("Agent.ListContainers", tArgs, &tReply, nil)
	<-ca.Done
	if ca.Error != nil {
		return ca.Error
	}
	*res = tReply.ListContainersDto
	return nil
}

func (ac *AgentClient) ReleaseContainer(param containerParam.ReleaseContainerParam, res *dto.ReleaseContainerDto) error {
	tArgs := &args.ReleaseContainerArgs{
		ReleaseContainerParam: param,
	}
	var tReply reply.ReleaseContainerReply
	ca := ac.client.Go("Agent.ReleaseContainer", tArgs, &tReply, nil)
	<-ca.Done
	if ca.Error != nil {
		return ca.Error
	}
	*res = tReply.ReleaseContainerDto
	return nil
}

func (ac *AgentClient) HasContainer(param containerParam.HasContainerParam, res *dto.HasContainerDto) error {
	tArgs := &args.HasContainerArgs{
		HasContainerParam: param,
	}
	var tReply reply.HasContainerReply
	ca := ac.client.Go("Agent.HasContainer", tArgs, &tReply, nil)
	<-ca.Done
	if ca.Error != nil {
		return ca.Error
	}
	*res = tReply.HasContainerDto
	return nil

}

func (ac *AgentClient) HealthCheckContainer(param containerParam.HealthCheckContainerParam, res *dto.HealthCheckContainerDto) error {
	tArgs := &args.HealthCheckContainerArgs{
		HealthCheckContainerParam: param,
	}
	var tReply reply.HealthCheckContainerReply
	ca := ac.client.Go("Agent.HealthCheckContainer", tArgs, tReply, nil)
	<-ca.Done
	if ca.Error != nil {
		return ca.Error
	}
	*res = tReply.HealthCheckContainerDto
	return nil
}
